import Callout from 'components/Callout';
import PartnerContentLink from 'components/PartnerContentLink';

# Date and time formatting

The formatting of dates and times varies greatly between locales (e.g. "Apr 24, 2023" in `en-US` vs. "24 квіт. 2023 р." in `uk-UA`). By using the formatting capabilities of `next-intl`, you can handle all i18n differences in your Next.js app automatically.

## Formatting dates and times

You can format plain dates that are not part of a message with the `useFormatter` hook:

```js
import {useFormatter} from 'next-intl';

function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T10:36:01.516Z');

  // Renders "Nov 20, 2020"
  format.dateTime(dateTime, {
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  });

  // Renders "11:36 AM"
  format.dateTime(dateTime, {hour: 'numeric', minute: 'numeric'});
}
```

See [the MDN docs about `DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#Using_options) to learn more about the options that you can provide to the `dateTime` function or [try the interactive explorer for `Intl.DateTimeFormat`](https://www.intl-explorer.com/DateTimeFormat).

<details>
<summary>How can I parse dates or manipulate them?</summary>

Since `next-intl` is only concerned with formatting dates, you can use a library like [date-fns](https://date-fns.org/) to manipulate them.

To parse dates, you can pass them to [the `Date` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date).

```tsx
import {subDays} from 'date-fns';

// Make sure your date string conforms to ISO 8601
const date = new Date('2020-11-20T10:36:01.516Z');

// 2020-11-18T10:36:01.516Z
const twoDaysAgo = subDays(date, 2);
```

</details>

## Formatting relative time

Relative time durations can be formatted with a separate function:

```js
import {useFormatter} from 'next-intl';

function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T08:30:00.000Z');
  const now = new Date('2020-11-20T10:36:00.000Z');

  // Renders "2 hours ago"
  format.relativeTime(dateTime, now);
}
```

Note that values are rounded, so e.g. if 100 seconds have passed, "2 minutes ago" will be returned.

If you want to use a specific unit, you can pass options with the second argument:

```js
import {useFormatter} from 'next-intl';

function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T08:30:00.000Z');
  const now = new Date('2020-11-20T10:36:00.000Z');

  // Renders "today"
  format.relativeTime(dateTime, { now, unit: 'day' });
}
```

Supplying `now` is necessary for the function to return consistent results. If you have [configured a global value for `now`](/docs/usage/configuration#now), you can omit the second argument:

```js
format.relativeTime(dateTime);
```

### `useNow`

If you want the relative time value to update over time, you can do so with the `useNow` hook:

```js
import {useNow, useFormatter} from 'next-intl';

function Component() {
  const now = useNow({
    // Update every 10 seconds
    updateInterval: 1000 * 10
  });
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T10:36:01.516Z');

  // Renders e.g. "2 hours ago" and updates continuously
  format.relativeTime(dateTime, now);
}
```

## Dates and times within messages

Dates and times can be embedded within messages by using the ICU syntax.

```json filename="en.json"
{
  "ordered": "Ordered on {orderDate, date, medium}"
}
```

These formats are supported out of the box: `full`, `long`, `medium` and `short`.

<Callout>

If you work with translators, it can be helpful for them to use an editor that supports the ICU syntax for dates and times (e.g. the <PartnerContentLink name="dates-times-messages" href="https://support.crowdin.com/icu-message-syntax/#date-time">Crowdin Editor</PartnerContentLink>).

</Callout>

You can customize the formatting by using date skeletons:

```json filename="en.json"
{
  "ordered": "Ordered on {orderDate, date, ::yyyyMd}"
}
```

Note the leading `::` that is used to indicate that a skeleton should be used.

**These formats from ICU are supported:**

| Symbol | Meaning                       |
| :----: | :---------------------------- |
|   G    | Era designator                |
|   y    | Year                          |
|   M    | Month in year                 |
|   L    | Stand-alone month in year     |
|   d    | Day in month                  |
|   E    | Day of week                   |
|   e    | Local day of week             |
|   c    | Stand-alone local day of week |
|   a    | AM/PM marker                  |
|   h    | Hour [1-12]                   |
|   H    | Hour [0-23]                   |
|   K    | Hour [0-11]                   |
|   k    | Hour [1-24]                   |
|   m    | Minute                        |
|   s    | Second                        |
|   z    | Time zone                     |

### Custom date and time formats

To use custom formats in messages, you can provide formatters based on [`DateTimeFormat` options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#Using_options) that can be referenced by name.

```json filename="en.json"
{
  "ordered": "Ordered on {orderDate, date, short}"
}
```

```js
t(
  'ordered',
  {orderDate: new Date('2020-11-20T10:36:01.516Z')},
  {
    dateTime: {
      short: {
        day: 'numeric',
        month: 'short',
        year: 'numeric'
      }
    }
  }
);
```

<Callout>
  To reuse date and time formats for multiple components, you can configure
  [global formats](/docs/usage/configuration#formats).
</Callout>
